﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
#if TASKSUPPORT
using System.Threading.Tasks;
#endif
using MugenMvvmToolkit.Interfaces;
using MugenMvvmToolkit.Interfaces.ViewModels;
using MugenMvvmToolkit.Models;

namespace MugenMvvmToolkit.Infrastructure
{
    /// <summary>
    ///     Represents a class that can validate the IValidatableViewModel
    /// </summary>
    public class ValidatableViewModelValidator : ValidatorBase<IValidatableViewModel>
    {
        #region Overrides of ValidatorBase

        /// <summary>
        ///     Indicates that can be only once instance of this validator.
        /// </summary>
        public override bool IsUnique
        {
            get { return false; }
        }

        /// <summary>
        ///     Gets the validation errors for a specified property or for the entire entity.
        /// </summary>
        /// <returns>
        ///     The validation errors for the property or entity.
        /// </returns>
        /// <param name="propertyName">
        ///     The name of the property to retrieve validation errors for; or null or <see cref="F:System.String.Empty" />, to
        ///     retrieve entity-level errors.
        /// </param>
        protected override IEnumerable GetErrorsInternal(string propertyName)
        {
            return InstanceToValidate.GetErrors(propertyName);
        }

        /// <summary>
        ///     Determines whether the current model is valid.
        /// </summary>
        /// <returns>
        ///     If <c>true</c> current model is valid, otherwise <c>false</c>.
        /// </returns>
        protected override bool IsValidInternal()
        {
            return InstanceToValidate.IsValid();
        }

        /// <summary>
        ///     Clears errors for a property.
        /// </summary>
        /// <param name="propertyName">The name of the property</param>
        protected override void ClearErrorsInternal(string propertyName)
        {
            InstanceToValidate.ClearErrors(propertyName);
        }

        /// <summary>
        ///     Clears the all errors.
        /// </summary>
        protected override void ClearErrorsInternal()
        {
            InstanceToValidate.ClearErrors();
        }

#if !NONOTIFYDATAERROR
        /// <summary>
        ///     Initializes the current validator using the specified <see cref="IValidatorContext" />.
        /// </summary>
        /// <param name="context">
        ///     The specified <see cref="IValidatorContext" />.
        /// </param>
        protected override void OnInitialized(IValidatorContext context)
        {
            InstanceToValidate.ErrorsChanged += InstanceToValidateOnErrorsChanged;
        }

        /// <summary>
        ///     Occurs after current view model disposed, use for clear resource and event listeners.
        /// </summary>
        protected override void OnDispose(bool disposing)
        {
            if (disposing)
                InstanceToValidate.ErrorsChanged -= InstanceToValidateOnErrorsChanged;
        }

        private void InstanceToValidateOnErrorsChanged(object sender, DataErrorsChangedEventArgs dataErrorsChangedEventArgs)
        {
            OnErrorsChanged(dataErrorsChangedEventArgs.PropertyName, true);
        }
#endif
        /// <summary>
        ///     Gets the all validation errors.
        /// </summary>
        /// <returns>
        ///     The validation errors.
        /// </returns>
        protected override IDictionary<string, IList<object>> GetAllErrorsInternal()
        {
            return InstanceToValidate.GetAllErrors();
        }

#if TASKSUPPORT
        /// <summary>
        ///     Updates information about errors in the specified property.
        /// </summary>
        /// <param name="propertyName">The specified property name.</param>        
        /// <returns>
        ///     The result of validation.
        /// </returns>
        protected override Task<IEnumerable> ValidateInternal(string propertyName)
        {
            InstanceToValidate.Validate(propertyName);
            return EmptyValidateResult;
        }

        /// <summary>
        ///     Updates information about all errors.
        /// </summary>
        /// <returns>
        ///     The result of validation.
        /// </returns>
        protected override Task<IDictionary<string, IEnumerable>> ValidateAllInternal()
        {
            InstanceToValidate.ValidateAll();
            return EmptyValidateAllResult;
        }
#else
        /// <summary>
        ///     Updates information about errors in the specified property.
        /// </summary>
        /// <param name="propertyName">The specified property name.</param>
        protected override IOperationResult<IEnumerable> ValidateInternal(string propertyName)
        {
            InstanceToValidate.Validate(propertyName);
            return EmptyListResult;
        }

        /// <summary>
        ///     Updates information about all errors.
        /// </summary>        
        protected override IOperationResult<IDictionary<string, IEnumerable>> ValidateAllInternal()
        {
            InstanceToValidate.ValidateAll();
            return EmptyDictionaryResult;
        }
#endif

        /// <summary>
        ///     Creates a new validator that is a copy of the current instance.
        /// </summary>
        /// <returns>
        ///     A new validator that is a copy of this instance.
        /// </returns>
        protected override IValidator CloneInternal()
        {
            return new ValidatableViewModelValidator();
        }

        #endregion
    }
}